home *** CD-ROM | disk | FTP | other *** search
- /* SampleTestPlay.c */
- /*****************************************************************************/
- /* */
- /* Out Of Phase: Digital Music Synthesis on General Purpose Computers */
- /* Copyright (C) 1994 Thomas R. Lawrence */
- /* */
- /* This program is free software; you can redistribute it and/or modify */
- /* it under the terms of the GNU General Public License as published by */
- /* the Free Software Foundation; either version 2 of the License, or */
- /* (at your option) any later version. */
- /* */
- /* This program is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- /* GNU General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU General Public License */
- /* along with this program; if not, write to the Free Software */
- /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- /* */
- /* Thomas R. Lawrence can be reached at tomlaw@world.std.com. */
- /* */
- /*****************************************************************************/
-
- #include "MiscInfo.h"
- #include "Audit.h"
- #include "Debug.h"
- #include "Definitions.h"
-
- #include "SampleTestPlay.h"
- #include "SoundOutput.h"
- #include "Memory.h"
- #include "SampleWindow.h"
- #include "SampleConsts.h"
- #include "FixedPoint.h"
-
- #define FRAMESPERBUFFER (8192)
- #define MAXBUFFERS (3)
- #define INITIALBUFFERS (MAXBUFFERS)
-
- #define SIXTEENBITSHIFTFACTOR (10)
- #define EIGHTBITSHIFTFACTOR (18)
-
-
- typedef enum
- {
- eNoPlay EXECUTE(= -18481),
- eLoopPlay,
- eNoLoopPlay,
- eWaiting
- } InternalStates;
-
- static InternalStates State = eNoPlay;
-
- static SampleTestErrors ErrorOccurred;
- static SampleWindowRec* Window;
- static largefixedsigned* Data;
- static long LoopStart;
- static long LoopEnd;
- static long CurrentIndex;
- static NumBitsType NumBits;
- static NumChannelsType NumChannels;
- static long EndOfChannel;
- static MyBoolean DoingLoop;
-
-
- MyBoolean SampleTestPlayInProgress(void)
- {
- return State != eNoPlay;
- }
-
-
- void SampleTestPlayCallback(SampleWindowRec* TheWindow, MyBoolean IgnoreMe)
- {
- void* Buffer;
- long Scan;
- long LocalIndex;
- long LocalEnd;
- largefixedsigned* LocalData;
- long Limit;
-
- if (State == eNoPlay)
- {
- SoundOutputStereo StereoRequest;
- SoundOutputNumBits BitsRequest;
-
- State = eLoopPlay;
- ErrorOccurred = eSampleTestNoError;
-
- Window = TheWindow;
-
- Data = SampleWindowGetRawFixedPointData(TheWindow);
- if (Data == NIL)
- {
- ErrorOccurred = eSampleTestNoSample;
- return;
- }
- SampleWindowFinalizeCurrentEdit(TheWindow);
- LoopStart = SampleWindowGetLoopStart(TheWindow);
- LoopEnd = SampleWindowGetLoopEnd(TheWindow);
- if (LoopEnd == LoopStart)
- {
- State = eNoLoopPlay;
- }
- CurrentIndex = 0;
- NumBits = SampleWindowGetNumBits(TheWindow);
- NumChannels = SampleWindowGetNumChannels(TheWindow);
- if (NumChannels == eSampleStereo)
- {
- StereoRequest = eStereo;
- }
- else
- {
- StereoRequest = eMono;
- }
- if (NumBits == eSample16bit)
- {
- BitsRequest = e16bit;
- }
- else
- {
- BitsRequest = e8bit;
- }
- if (!OpenSoundChannel(SampleWindowGetSamplingRate(TheWindow),
- StereoRequest,BitsRequest,FRAMESPERBUFFER,MAXBUFFERS,INITIALBUFFERS))
- {
- ErrorOccurred = eSampleTestCouldntOpenChannel;
- return;
- }
- DoingLoop = True;
- EndOfChannel = PtrSize((char*)Data) / sizeof(largefixedsigned);
- if (NumChannels == eSampleStereo)
- {
- EndOfChannel = EndOfChannel / 2;
- }
- }
-
- if (State == eWaiting)
- {
- return;
- }
- if (ErrorOccurred != eSampleTestNoError)
- {
- return;
- }
- ERROR(Window != TheWindow,PRERR(ForceAbort,
- "SampleTestPlayCallback: window pointers are different"));
-
- /* set up local variable values */
- Buffer = CheckOutSoundBuffer();
- if (Buffer == NIL)
- {
- return;
- }
- Scan = 0;
- LocalIndex = CurrentIndex;
- LocalData = Data;
- Limit = FRAMESPERBUFFER;
-
- /* use one of the 8 synthesis techniques */
- if (State == eNoLoopPlay)
- {
- LocalEnd = EndOfChannel; /* for no loop, the end is the real end */
- if (NumChannels == eSampleStereo)
- {
- if (NumBits == eSample16bit)
- {
- /* stereo, 16-bit, no loop */
- PRNGCHK(Buffer,Buffer,sizeof(short) * Limit * 2);
- while (Scan < Limit)
- {
- if (LocalIndex >= LocalEnd)
- {
- goto AllDonePoint;
- }
- ((signed short*)Buffer)[Scan * 2 + 0]
- = LocalData[LocalIndex * 2 + 0] >> SIXTEENBITSHIFTFACTOR;
- ((signed short*)Buffer)[Scan * 2 + 1]
- = LocalData[LocalIndex * 2 + 1] >> SIXTEENBITSHIFTFACTOR;
- LocalIndex += 1;
- Scan += 1;
- }
- }
- else
- {
- /* stereo, 8-bit, no loop */
- PRNGCHK(Buffer,Buffer,sizeof(char) * Limit * 2);
- while (Scan < Limit)
- {
- if (LocalIndex >= LocalEnd)
- {
- goto AllDonePoint;
- }
- ((signed char*)Buffer)[Scan * 2 + 0]
- = LocalData[LocalIndex * 2 + 0] >> EIGHTBITSHIFTFACTOR;
- ((signed char*)Buffer)[Scan * 2 + 1]
- = LocalData[LocalIndex * 2 + 1] >> EIGHTBITSHIFTFACTOR;
- LocalIndex += 1;
- Scan += 1;
- }
- }
- }
- else
- {
- if (NumBits == eSample16bit)
- {
- /* mono, 16-bit, no loop */
- PRNGCHK(Buffer,Buffer,sizeof(short) * Limit);
- while (Scan < Limit)
- {
- if (LocalIndex >= LocalEnd)
- {
- goto AllDonePoint;
- }
- ((signed short*)Buffer)[Scan]
- = LocalData[LocalIndex] >> SIXTEENBITSHIFTFACTOR;
- LocalIndex += 1;
- Scan += 1;
- }
- }
- else
- {
- /* mono, 8-bit, no loop */
- PRNGCHK(Buffer,Buffer,sizeof(char) * Limit);
- while (Scan < Limit)
- {
- if (LocalIndex >= LocalEnd)
- {
- goto AllDonePoint;
- }
- ((signed char*)Buffer)[Scan]
- = LocalData[LocalIndex] >> EIGHTBITSHIFTFACTOR;
- LocalIndex += 1;
- Scan += 1;
- }
- }
- }
- goto SubmitPoint;
- /* skip this */
- AllDonePoint:
- /* end of channel, time to stop playing */
- SubmitBuffer((char*)Buffer,Scan,NIL,NIL);
- State = eWaiting;
- return;
- }
- else
- {
- LocalEnd = LoopEnd; /* for loop, this is what the end is */
- if (NumChannels == eSampleStereo)
- {
- if (NumBits == eSample16bit)
- {
- /* stereo, 16-bit, yes loop */
- PRNGCHK(Buffer,Buffer,sizeof(short) * Limit * 2);
- while (Scan < Limit)
- {
- if (LocalIndex == LocalEnd)
- {
- LocalIndex = LoopStart;
- }
- ((signed short*)Buffer)[Scan * 2 + 0]
- = LocalData[LocalIndex * 2 + 0] >> SIXTEENBITSHIFTFACTOR;
- ((signed short*)Buffer)[Scan * 2 + 1]
- = LocalData[LocalIndex * 2 + 1] >> SIXTEENBITSHIFTFACTOR;
- LocalIndex += 1;
- Scan += 1;
- }
- }
- else
- {
- /* stereo, 8-bit, yes loop */
- PRNGCHK(Buffer,Buffer,sizeof(char) * Limit * 2);
- while (Scan < Limit)
- {
- if (LocalIndex == LocalEnd)
- {
- LocalIndex = LoopStart;
- }
- ((signed char*)Buffer)[Scan * 2 + 0]
- = LocalData[LocalIndex * 2 + 0] >> EIGHTBITSHIFTFACTOR;
- ((signed char*)Buffer)[Scan * 2 + 1]
- = LocalData[LocalIndex * 2 + 1] >> EIGHTBITSHIFTFACTOR;
- LocalIndex += 1;
- Scan += 1;
- }
- }
- }
- else
- {
- if (NumBits == eSample16bit)
- {
- /* mono, 16-bit, yes loop */
- PRNGCHK(Buffer,Buffer,sizeof(short) * Limit);
- while (Scan < Limit)
- {
- if (LocalIndex == LocalEnd)
- {
- LocalIndex = LoopStart;
- }
- ((signed short*)Buffer)[Scan]
- = LocalData[LocalIndex] >> SIXTEENBITSHIFTFACTOR;
- LocalIndex += 1;
- Scan += 1;
- }
- }
- else
- {
- /* mono, 8-bit, yes loop */
- PRNGCHK(Buffer,Buffer,sizeof(char) * Limit);
- while (Scan < Limit)
- {
- if (LocalIndex == LocalEnd)
- {
- LocalIndex = LoopStart;
- }
- ((signed char*)Buffer)[Scan]
- = LocalData[LocalIndex] >> EIGHTBITSHIFTFACTOR;
- LocalIndex += 1;
- Scan += 1;
- }
- }
- }
- }
-
- /* play the data and write changed values out */
- SubmitPoint:
- SubmitBuffer((char*)Buffer,Limit,NIL,NIL);
- CurrentIndex = LocalIndex;
- }
-
-
- void SampleTestBreakLoop(void)
- {
- ERROR(State != eLoopPlay,PRERR(ForceAbort,
- "SampleTestBreakLoop: cancelling loop but it isn't looping"));
- State = eNoLoopPlay;
- }
-
-
- SampleTestErrors SampleTestDidErrorOccur(void)
- {
- return ErrorOccurred;
- }
-
-
- void SampleTestPlayCleanup(void)
- {
- ERROR(State == eNoPlay,PRERR(ForceAbort,
- "SampleTestPlayCleanup: nothing is playing"));
- CloseSoundChannel(NIL,NIL);
- State = eNoPlay;
- }
-
-
- MyBoolean SampleTestIsItLooping(void)
- {
- return State == eLoopPlay;
- }
-
-
- MyBoolean SampleTestIsWaitingForCleanup(void)
- {
- return State == eWaiting;
- }
-